﻿using Flow.Manage.Contracts;
using Framework.Code.FlowWork;
using Framework.Models;
using Framework.Models.Entities;
using Framework.Models.Request;
using Framework.Repository;
using Framework.Utility;
using Framework.Utility.Helper;
using Framework.Utility.ViewModels;
using Microsoft.EntityFrameworkCore;

namespace Flow.Manage.Service
{
    public class WorkFlowService : IWorkFlowContract
    {
        private readonly IFlowschemeRepository _flowschemeRepository;
        private readonly IFlowinstanceRepository _flowinstanceRepository;
        private readonly FlowHandle _flowHandle;

        public WorkFlowService(IFlowschemeRepository flowschemeRepository, IFlowinstanceRepository flowinstanceRepository, FlowHandle flowHandle)
        {
            _flowschemeRepository = flowschemeRepository;
            _flowinstanceRepository = flowinstanceRepository;
            _flowHandle = flowHandle;
        }

        #region Flowscheme

        public async Task<TData<List<Fw_Flowscheme>>> GetFlowschemeList()
        {
            TData<List<Fw_Flowscheme>> tData = new TData<List<Fw_Flowscheme>>();
            tData.data = await _flowschemeRepository.EntitiesAsNoTracking.ToListAsync();
            return tData;
        }

        /// <summary>
        /// 根据schemeId 获取 流程模板信息
        /// </summary>
        /// <param name="schemeId"></param>
        /// <returns></returns>
        public async Task<TData> GetFlowschemeById(string schemeId)
        {
            TData tData = new TData(ResultTag.success);
            tData.data = await _flowschemeRepository.GetByKeyAsync(schemeId);
            return tData;
        }

        public TData<Fw_Flowscheme> FindFlowschemeByCode(string code)
        {
            TData<Fw_Flowscheme> tData = new TData<Fw_Flowscheme>();
            tData.data = _flowschemeRepository.GetFirstOrDefault(u => u.SchemeCode == code);
            return tData;
        }

        public async Task<TData> AddFlowScheme(Fw_FlowschemeRequest param)
        {
            var flowScheme = param.MapTo<Fw_Flowscheme>();

            if (_flowschemeRepository.CheckExists(u => u.SchemeName == flowScheme.SchemeName))
            {
                throw new Exception("流程名称已经存在");
            }
            flowScheme.Id = SnowflakeId.Default().NextId().ToString();
            flowScheme.CreateTime = DateTime.Now;
            flowScheme.CreateBy = "system";
            var count = await _flowschemeRepository.InsertAsync(flowScheme);
            return count > 0 ? new TData(ResultTag.success) : new TData(ResultTag.fail);
        }

        public async Task<TData> UpdateFlowscheme(Fw_FlowschemeRequest flowScheme)
        {
            var model = await _flowschemeRepository.GetByKeyAsync(flowScheme.Id);
            if (model == null)
            {
                throw new Exception("流程不存在");
            }
            model.SchemeCode = flowScheme.SchemeCode;
            model.SchemeName = flowScheme.SchemeName;
            model.SchemeCanUser = flowScheme.SchemeCanUser;
            model.SchemeVersion = flowScheme.SchemeVersion;
            model.SchemeType = flowScheme.SchemeType;
            model.SchemeContent = flowScheme.SchemeContent;
            model.FrmContentData = flowScheme.FrmContentData;
            model.Description = flowScheme.Description;
            model.DeduplicationType = flowScheme.DeduplicationType;
            model.UpdateBy = "system";
            model.UpdateTime = DateTime.Now;
            int count = await _flowschemeRepository.UpdateAsync(model);
            return count > 0 ? new TData(ResultTag.success) : new TData(ResultTag.fail);
        }

        /// <summary>
        /// 删除流程模板
        /// </summary>
        /// <param name="schemeId">流程模板id</param>
        /// <returns></returns>
        public async Task<TData> DelFlowScheme(string schemeId)
        {
            var entity = await _flowschemeRepository.GetByKeyAsync(schemeId);
            entity.IsDisabled = true;
            entity.IsDeleted = true;
            entity.UpdateTime = DateTime.Now;
            entity.UpdateBy = "system";
            var count = _flowschemeRepository.Update(entity);
            return count > 0 ? new TData(ResultTag.success) : new TData(ResultTag.fail);
        }

        #endregion Flowscheme

        /// <summary>
        /// 注册审批流程
        /// </summary>
        /// <param name="model"></param>
        /// <param name="flowScheme"></param>
        /// <returns></returns>
        public TData RegisterFlow(RegisterFlow model, object obj)
        {
            var flowScheme = _flowschemeRepository.GetByKey(model.flowSchemeId);
            //获取条件节点 的 判断条件
            model.frmData = _flowHandle.GetFrmData(obj, flowScheme.FrmContentData);
            return StartFlowinstance(model, flowScheme);
        }

        /// <summary>
        /// 获取流程实例列表
        /// </summary>
        /// <returns></returns>
        public async Task<TData<object>> GetFlowinstanceList()
        {
            TData<object> tData = new TData<object>();
            tData.data = await _flowinstanceRepository.EntitiesAsNoTracking.ToArrayAsync();
            tData.total = await _flowinstanceRepository.EntitiesAsNoTracking.CountAsync();
            return tData;
        }

        /// <summary>
        /// 流程实例预览
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<TData<object>> GetFlowinstancebyId(string Id)
        {
            var instance = await _flowinstanceRepository.GetByKeyAsync(Id);
            FlowRuntime flowRuntime = new FlowRuntime(instance);
            TData<object> tData = new TData<object>();
            tData.data = _flowHandle.GetApprovalNodeList(flowRuntime);
            return tData;
        }

        public TData AddFlowinstance(Fw_FlowinstanceRequest param)
        {
            var flowscheme = _flowschemeRepository.GetFirstOrDefault(u => u.Id == param.SchemeId);

            if (flowscheme == null)
            {
                throw new Exception("流程模板不存在");
            }
            var instance = param.MapTo<Fw_Flowinstance>();
            instance.Id = SnowflakeId.Default().NextId().ToString();
            instance.SchemeContent = flowscheme.SchemeContent;
            instance.FrmContentData = flowscheme.FrmContentData;
            instance.ConfluenceNo = 0;
            instance.ConfluenceOk = 0;

            FlowRuntime flowRuntime = new FlowRuntime(instance);

            instance.ActivityId = flowRuntime.currentNodeId;
            instance.ActivityName = flowRuntime.nodeName;
            instance.ActivityType = (int)flowRuntime.currentNodeType;
            instance.PreviousId = flowRuntime.previousId;
            instance.MakerList = _flowHandle.GetNextMakers(flowRuntime);

            instance.CreateTime = DateTime.Now;
            instance.CreateBy = "system";
            var count = _flowinstanceRepository.Insert(instance);

            return count > 0 ? new TData(ResultTag.success) : new TData(ResultTag.fail);
        }

        /// <summary>
        /// 发起审批流程
        /// </summary>
        /// <param name="model"></param>
        /// <param name="flowScheme"></param>
        /// <returns></returns>
        public TData StartFlowinstance(RegisterFlow model, Fw_Flowscheme flowScheme)
        {
            var instance = new Fw_Flowinstance();
            instance.Id = model.flowInstanceId;

            instance.FlowCode = model.flowInstanceId;
            instance.CustomName = model.flowInstanceName;
            instance.FlowLevel = model.FlowLevel;
            instance.ApplyUserId = model.applyUserId;
            instance.ApplyUserName = model.applyUserName;
            instance.SchemeId = flowScheme.Id;
            instance.SchemeContent = flowScheme.SchemeContent;
            instance.FrmContentData = flowScheme.FrmContentData;
            instance.ConfluenceNo = 0;
            instance.ConfluenceOk = 0;
            instance.FrmContentData = flowScheme.FrmContentData;
            instance.FrmData = model.frmData;

            FlowRuntime flowRuntime = new FlowRuntime(instance);
            instance.PreviousId = flowRuntime.currentNodeId;
            instance.ActivityId = flowRuntime.nextNodeId;
            instance.ActivityName = flowRuntime.nextNode?.nodeName ?? Define.FlowEndTitle;
            instance.ActivityType = flowRuntime.nextNode?.nodeType ?? (int)FlowNodeType.End;
            instance.MakerList = _flowHandle.GetNextMakers(flowRuntime);
            instance.CreateTime = DateTime.Now;
            instance.CreateBy = model.applyUserName;

            var count = _flowinstanceRepository.Insert(instance);
            return count > 0 ? new TData(ResultTag.success) : new TData(ResultTag.fail);
        }

        public TData UpdateFlowinstance(Fw_FlowinstanceRequest param)
        {
            var model = _flowschemeRepository.GetByKey(param.SchemeId);
            if (model == null)
            {
                throw new Exception("流程模板不存在");
            }
            var entity = _flowinstanceRepository.GetByKey(param.Id);
            if (entity.CustomName == param.CustomName)
            {
                throw new Exception("流程名称已经存在");
            }
            entity.SchemeContent = model.SchemeContent;
            entity.UpdateTime = DateTime.Now;
            entity.UpdateBy = "system";
            var count = _flowinstanceRepository.Update(entity);
            return count > 0 ? new TData(ResultTag.success) : new TData(ResultTag.fail);
        }

        #region 审批操作

        /// <summary>
        /// 审批
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public TData FlowApproval(ApprovalReqest param)
        {
            _flowHandle.Approval(param);
            return new TData(ResultTag.success);
        }

        /// <summary>
        /// 发起审批流程
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public TData FlowStart(string instanceId)
        {
            _flowHandle.Start(instanceId);
            return new TData(ResultTag.success);
        }

        /// <summary>
        /// 召回审批流程
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public TData FlowReCall(string instanceId)
        {
            _flowHandle.ReCall(instanceId);
            return new TData(ResultTag.success);
        }

        #endregion 审批操作
    }
}